#include <cstdio>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <app.h>
#include <shader.h>

const char *vscode = 
"#version 330 core \n"
"layout(location = 0) in vec4 pos; \n"
"layout(location = 1) in vec4 color; \n"
"uniform float xoffset; \n"
"out vec4 outcolor; \n"
"\n"
"void main() \n"
"{\n"
"   gl_Position = pos + vec4(xoffset, 0.0, 0.0, 0.0); \n"
"   outcolor = color; \n"
"}";

const char *fscode = 
"#version 330 core \n"
"in vec4 outcolor; \n"
"out vec4 color; \n"
"\n"
"void main() \n"
"{ \n"
"   color = outcolor; \n"
"}";

const float arrdata[] = {
    -0.25f,   0.0f, 0.0f,   1.0f, 0.0f, 0.0f,
     0.25f,   0.0f, 0.0f,   1.0f, 0.0f, 0.0f,
      0.0f,  0.25f, 0.0f,   1.0f, 0.0f, 0.0f,

    -0.25f, -0.15f, 0.5f,   0.0f, 1.0f, 0.0f,
     0.25f, -0.15f, 0.5f,   0.0f, 1.0f, 0.0f,
      0.0f,   0.1f, 0.5f,   0.0f, 1.0f, 0.0f,
};

static GLuint _program, _vao, _bo;
static GLuint _xoffset_loc;

static GLboolean 
cb_init(GLFWwindow *wnd) {
    _program = shader_linkprogram_str(vscode, fscode);
    if (_program == 0)
        return GL_FALSE;

    _xoffset_loc = glGetUniformLocation(_program, "xoffset");

    glGenBuffers(1, &_bo);
    glBindBuffer(GL_ARRAY_BUFFER, _bo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(arrdata), arrdata, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    float *offset = NULL;
    GLsizei stride = sizeof(float) * 6;
    glGenVertexArrays(1, &_vao);
    glBindVertexArray(_vao);
        glBindBuffer(GL_ARRAY_BUFFER, _bo);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, offset);

        offset += 3;
        glEnableVertexAttribArray(1);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, offset);
    glBindVertexArray(0);

    glEnable(GL_DEPTH_TEST);
    return GL_TRUE;
}

static void
cb_render(GLFWwindow *wnd, double current, int w, int h) {
    static float black[] = {0.0f, 0.0f, 0.0f, 1.0f};
    static float one = 1.0f;
    glClearBufferfv(GL_COLOR, 0, black);
    glClearBufferfv(GL_DEPTH, 0, &one);

    glUseProgram(_program);
        glBindVertexArray(_vao);
            glDepthRangef(0.0f, 1.0f);
            glUniform1f(_xoffset_loc, -0.5f);
            glDrawArrays(GL_TRIANGLES, 0, 6);

            glDepthRangef(1.0f, 0.0f);
            glUniform1f(_xoffset_loc, 0.5f);
            glDrawArrays(GL_TRIANGLES, 0, 6);
        glBindVertexArray(0);
    glUseProgram(0);
}

static void
cb_destroy() {
    glDeleteProgram(_program);
    glDeleteVertexArrays(1, &_vao);
    glDeleteBuffers(1, &_bo);
}

int 
main() {
    if (!app_init(400, 300, "view depth range", cb_init))
        return 0;
    app_run(cb_render);
    app_destroy(cb_destroy);
    return 0;
}
